package nut.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import nut.common.handler.exceptionhandler.MyException;
import nut.common.utils.AgeUtil;
import nut.common.utils.JwtUtil;
import nut.entity.*;
import nut.entity.vo.RecruitWithScoreVo;
import nut.mapper.*;
import nut.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author 郜宇博
 * @since 2021-12-19
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    private final RecruitMapper recruitMapper;
    private final EnterpriseResumeMapper enterpriseResumeMapper;
    private final ResumeBaseInfoMapper resumeBaseInfoMapper;
    private final ResumeMapper resumeMapper;
    private final ScoreMap scoreMap;
    private final EnterpriseDisplayMapper enterpriseDisplayMapper;



    public UserServiceImpl(RecruitMapper recruitMapper,
                           EnterpriseResumeMapper enterpriseResumeMapper,
                           ResumeBaseInfoMapper resumeBaseInfoMapper,
                           ResumeMapper resumeMapper, ScoreMap scoreMap,
                           EnterpriseDisplayMapper enterpriseDisplayMapper) {
        this.recruitMapper = recruitMapper;
        this.enterpriseResumeMapper = enterpriseResumeMapper;
        this.resumeBaseInfoMapper = resumeBaseInfoMapper;
        this.resumeMapper = resumeMapper;
        this.scoreMap = scoreMap;
        this.enterpriseDisplayMapper = enterpriseDisplayMapper;
    }

    /**
     * 登录
     * @param user 传入的user
     * @return jwt
     */
    @Override
    public String login(User user) {
        String username = user.getUsername();
        String password = user.getPassword();
        //非空校验
        if (StringUtils.isEmpty(username)||StringUtils.isEmpty(password)){
            throw new MyException(20001,"账号或密码为空");
        }
        //判断用户名是否正确
        User loginUser = baseMapper.selectOne(new QueryWrapper<User>()
                .eq("username", username));
        if (loginUser == null){
            throw new MyException(20001,"用户名不存在");
        }
        //判断密码
        if (!password.equals(loginUser.getPassword())){
            throw new MyException(20001,"密码错误");
        }
        //登录成功
        return JwtUtil.getJwtToken(String.valueOf(loginUser.getUid()), username);
    }
    /**
     * 注册
     * @param user 用户信息
     */
    @Override
    public void register(User user) {
        //获取注册数据
        String username = user.getUsername();
        String password = user.getPassword();
        String telephone = user.getPhone();
        String email = user.getEmail();
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password) || StringUtils.isEmpty(telephone)|| StringUtils.isEmpty(email)){
            throw new MyException(20001,"注册失败，信息不完整");
        }
        //提高效率，只需要查询是否存在，不需要查出具体对象
        Integer count = baseMapper.selectCount(new QueryWrapper<User>().eq("username", username));
        if (count > 0){
            throw new MyException(20001,"用户名已经注册");
        }
        //数据添加数据库中
        User registerUser = new User();
        registerUser.setUsername(username);
        registerUser.setPassword(password);
        registerUser.setPhone(telephone);
        registerUser.setEmail(email);
        baseMapper.insert(user);
    }
    /**
     * 通过token获取用户
     * @return user
     */
    @Override
    public User getUserByToken(HttpServletRequest request) {
        //根据token获取到memberId
        String userId = JwtUtil.getMemberIdByJwtToken(request);
        //查询数据库
        return baseMapper.selectById(userId);
    }

    /**
     * 添加简历基本信息
     * @param resumeBaseInfo 简历信息
     * @return 是否添加成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addResumeBaseInfo(ResumeBaseInfo resumeBaseInfo,int uid) {
        //非空校验
        boolean hasEmpty = judgeResumeBaseInfoEmpty(resumeBaseInfo);
        if (hasEmpty){
            throw new MyException(20001,"基础信息填写不全");
        }
        resumeBaseInfoMapper.insert(resumeBaseInfo);
        //获取最新添加的简历（获取resumeId）
        QueryWrapper<ResumeBaseInfo> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("resume_id").last("limit 1");
        ResumeBaseInfo resumeBaseInfoHasId = resumeBaseInfoMapper.selectOne(wrapper);
        int resumeId = resumeBaseInfoHasId.getResumeId();
        //更新用户的resumeId
        User user = this.getById(uid);
        user.setResumeId(resumeId);
        this.updateById(user);
        return resumeId;
    }

    /**
     * 简历基本信息校验
     * @param resumeBaseInfo 简历信息
     * @return 是否存在null值
     */
    private boolean judgeResumeBaseInfoEmpty(ResumeBaseInfo resumeBaseInfo){
        String name = resumeBaseInfo.getName();
        String phone = resumeBaseInfo.getPhone();
        Date birthday = resumeBaseInfo.getBirthday();
        Integer gender = resumeBaseInfo.getGender();
        Integer marry = resumeBaseInfo.getMarry();
        String email = resumeBaseInfo.getEmail();
        boolean hasEmpty;
        hasEmpty = (StringUtils.isEmpty(name))||(StringUtils.isEmpty(phone))||(StringUtils.isEmpty(birthday))||(StringUtils.isEmpty(gender))||(StringUtils.isEmpty(marry))||(StringUtils.isEmpty(email));
        return hasEmpty;
    }
    /**
     * 添加简历关键信息
     * @param resumeCoreInfo 简历关键信息
     * @param resumeId 简历id
     * @return 是否添加成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addResumeCoreInfo(Resume resumeCoreInfo, int resumeId) {
        boolean hasEmpty = judgeResumeCoreInfoEmpty(resumeCoreInfo, resumeId);
        if (hasEmpty){
            throw new MyException(20001,"核心信息填写不全");
        }
        //添加简历关键信息
        resumeCoreInfo.setResumeId(resumeId);
        resumeMapper.insert(resumeCoreInfo);
        return true;
    }

    /**
     * 投递简历
     *
     * @param recruitId 招聘id
     * @param resumeId  简历id
     * @param uid       用户id
     * @return flag
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitResume(int recruitId, int resumeId, int uid) {
        //查询是否投递过简历
        QueryWrapper<EnterpriseResume> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("resume_id",resumeId).eq("recruit_id",recruitId);
        Integer count = enterpriseResumeMapper.selectCount(queryWrapper);
        if (count !=0 ){
            throw new MyException(20001,"投递过该招聘岗位");
        }
        //打分操作
        String score = getResumeScore(recruitId,resumeId);
        EnterpriseResume enterpriseResume = new EnterpriseResume();
        //获取eid
        int eid = recruitMapper.selectById(recruitId).getEid();
        enterpriseResume.setResumeId(resumeId);
        enterpriseResume.setRecruitId(recruitId);
        enterpriseResume.setEid(eid);
        enterpriseResume.setScore(score);
        //添加到招聘-简历中
        enterpriseResumeMapper.insert(enterpriseResume);
        //更新是否投递
        Resume resume = resumeMapper.selectById(resumeId);
        resume.setSend(1);
        resumeMapper.updateById(resume);
        return true;
    }

    /**
     * 获取所有招聘，并匹配自己的简历打分
     *
     * @param resumeId 简历id
     * @return recruitList
     */
    @Override
    public List<RecruitWithScoreVo> getRecruitsWithScore(int resumeId) {
        //获取所有招聘
        List<Recruit> recruits = recruitMapper.selectList(null);
        //简历打分，获取带分招聘
        return getRecruitsWithScore(resumeId,recruits);
    }

    /**
     * 更新简历基础信息
     *
     * @param resumeBaseInfo 简历基础信息
     * @param resumeId       简历id
     * @return flag
     */
    @Override
    public boolean updateResumeBaseInfo(ResumeBaseInfo resumeBaseInfo, int resumeId) {
        //判空
        boolean hasEmpty = judgeResumeBaseInfoEmpty(resumeBaseInfo);
        if (hasEmpty){
            throw new MyException(20001,"信息填写不完整");
        }
        int changeCount = resumeBaseInfoMapper.update(resumeBaseInfo, new QueryWrapper<ResumeBaseInfo>().eq("resume_id", resumeId));
        if (changeCount == 0){
            throw new MyException(20001,"更新失败或无改动");
        }
        return true;
    }

    /**
     * 更新简历核心信息
     *
     * @param resumeCoreInfo 简历核心信息
     * @param resumeId       简历id
     * @return flag
     */
    @Override
    public boolean updateResumeCoreInfo(Resume resumeCoreInfo, int resumeId) {
        //判空
        boolean hasEmpty = judgeResumeCoreInfoEmpty(resumeCoreInfo,resumeId);
        if (hasEmpty){
            throw new MyException(20001,"信息填写不完整");
        }
        int changeCount = resumeMapper.update(resumeCoreInfo, new QueryWrapper<Resume>().eq("resume_id", resumeId));
        if (changeCount == 0){
            throw new MyException(20001,"更新失败或无改动");
        }
        return true;
    }

    /**
     * 获取带分招聘信息
     * @param resumeId 简历id
     * @param recruits 招聘id
     * @return recruitList
     */
    private List<RecruitWithScoreVo> getRecruitsWithScore(int resumeId, List<Recruit> recruits) {
        List<RecruitWithScoreVo> recruitList = new ArrayList<>();
        for (Recruit recruit: recruits){
            //转化为recruitList
            RecruitWithScoreVo recruitWithScoreVo = new RecruitWithScoreVo();
            BeanUtils.copyProperties(recruit,recruitWithScoreVo);
            //获取招聘id
            int recruitId = recruit.getRecruitId();
            //赋值分数和名称
            String score = getResumeScore(recruitId, resumeId);
            recruitWithScoreVo.setScore(score);
            //获取企业名称
            EnterpriseDisplay enterprise = enterpriseDisplayMapper.selectById(recruit.getEid());
            recruitWithScoreVo.setEnterpriseName(enterprise.getName());
            recruitList.add(recruitWithScoreVo);
        }
        return recruitList;
    }

    /**
     * 打分
     * @return 分数
     */
    @Override
    public String getResumeScore(int recruitId, int resumeId) {
        //获取简历基本信息和核心信息
        ResumeBaseInfo resumeBaseInfo = resumeBaseInfoMapper.selectById(resumeId);
        Resume resumeCoreInfo = resumeMapper.selectById(resumeId);
        //判空
        if (resumeBaseInfo == null || resumeCoreInfo == null){
            throw new MyException(20001,"无简历");
        }
        //获取招聘表
        Recruit recruit = recruitMapper.selectById(recruitId);
        //0男，1女，2不限
        Integer genderRequire = recruit.getGenderRequire();
        //0男，1女
        Integer gender = resumeBaseInfo.getGender();
        String result;
        //如果性别匹配，才开始
        if (genderRequire == 2 || genderRequire.equals(gender)){
            Score score = new Score();
            //1.岗位
            int positionScore;
            if (recruit.getPosition().contains(resumeCoreInfo.getAimJobPosition())){
                positionScore = 60;
                if (recruit.getPosition().equals(resumeCoreInfo.getAimJobPosition())){
                    positionScore = 100;
                }
            }else {
                positionScore = 0;
            }
            //2.工作地
            int workplaceScore;
            if (recruit.getWorkplace().contains(resumeCoreInfo.getDesiredWorkplace())){
                workplaceScore = 80;
                if (recruit.getWorkplace().equals(resumeCoreInfo.getDesiredWorkplace())){
                    workplaceScore = 100;
                }
            }else {
                workplaceScore = 40;
            }
            //3.专业
            int majorScore;
            if (recruit.getMajorRequire().contains(resumeCoreInfo.getMajor())){
                majorScore = 80;
                if (recruit.getMajorRequire().equals(resumeCoreInfo.getMajor())){
                    majorScore = 100;
                }
            }else {
                majorScore = 0;
            }
            //4.薪资
            int salaryScore;
            //计算差值
            int diffSalary = Math.abs(Integer.parseInt(recruit.getSalary())  - Integer.parseInt(resumeCoreInfo.getSalaryRequire()));
            //(]
            if (diffSalary > 4000 && diffSalary <= 5000){
                salaryScore = 40;
            }else if (diffSalary > 3000 && diffSalary <= 4000){
                salaryScore = 60;
            }else if (diffSalary > 2000 && diffSalary <= 3000){
                salaryScore = 70;
            }else if (diffSalary > 1000 && diffSalary <= 2000){
                salaryScore = 80;
            }else if (diffSalary >=0  && diffSalary <= 1000){
                salaryScore = 100;
            }else {
                salaryScore = 20;
            }
            //5.院校
            int eduScore;
            //如果是985，211满分
            if (scoreMap.getSchoolList().contains(resumeCoreInfo.getGraduated())){
                eduScore = 100;
            }else {
                //要求本科
                if (recruit.getEducationRequire().contains("本科")){
                    if (resumeCoreInfo.getGraduated().contains("大学")){
                        eduScore = 80;
                    }else {//不满足本科要求
                        eduScore = 0;
                    }
                }else {//没有本科要求
                    eduScore = 60;
                }
            }
            //6.年龄
            int ageScore;
            int ageRequire = AgeUtil.getRequeireAge(recruit.getAgeRequire());
            //计算差值
            //格式化时间
            String strDateFormat = "yyyy-MM-dd HH:mm:ss";
            SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
            String birthday = sdf.format(resumeBaseInfo.getBirthday());
            int age = AgeUtil.getAge(birthday);
            int diffAge = Math.abs(ageRequire  - age);
            if (diffAge >=0 && diffAge <= 3){
                ageScore = 100;
            }else if (diffAge >= 4 && diffAge <= 6){
                ageScore = 70;
            }else if (diffAge >=7 && diffAge <= 10){
                ageScore = 50;
            }else {
                ageScore = 20;
            }
            score.setPosition(positionScore);
            score.setWorkplace(workplaceScore);
            score.setAge(ageScore);
            score.setMajor(majorScore);
            score.setSalary(salaryScore);
            score.setEducation(eduScore);
            System.out.println(score);
            result = String.valueOf(score.getSum(scoreMap));
        }else {
            result = "0";
        }
        return result;
    }
    /**
     * 简历关键信息校验
     * @param resumeCoreInfo 简历关键信息
     * @param resumeId       简历id
     * @return 是否存在null值
     */
    private boolean judgeResumeCoreInfoEmpty(Resume resumeCoreInfo, int resumeId){
        String aimJobPosition = resumeCoreInfo.getAimJobPosition();
        String jobCategory = resumeCoreInfo.getJobCategory();
        boolean hasEmpty;
        hasEmpty = (StringUtils.isEmpty(aimJobPosition)) ||(StringUtils.isEmpty(jobCategory)) || (resumeId == 0);
        return hasEmpty;
    }
}
